using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AvaloniaApplication1.IServices;
using AvaloniaApplication1.Models;
using AvaloniaApplication1.Util;
using MQTTnet;
using MQTTnet.Protocol;

namespace AvaloniaApplication1.Services;

public class MqttDeviceManager : IMqttDeviceManager
{
    private readonly MqttClientFactory _mqttFactory;
    private readonly IMessageParser _messageParser;

    /// <summary>
    /// 设备列表
    /// </summary>
    private readonly ConcurrentDictionary<string, MqttDeviceModel> _devices = new();

    public MqttDeviceManager()
    {
        _mqttFactory = new MqttClientFactory();
        _messageParser = new MessageParser();
    }

    /// <summary>
    /// 添加设备
    /// </summary>
    /// <param name="deviceId">设备Id</param>
    /// <param name="server">服务器地址</param>
    /// <param name="port">端口号</param>
    /// <param name="username">用户名</param>
    /// <param name="password">密码</param>
    /// <param name="topicoptions">主题p配置</param>
    /// <param name="isConnected">连接状态</param>
    /// <param name="qos">QOS等级</param>
    /// <returns></returns>
    public async Task<bool> AddDeviceAsync(string deviceId, string server, int port, string username, string password,
        List<MqttTopicConfig> topicoptions, bool isConnected = false)
    {
        try
        {
            if (_devices.ContainsKey(deviceId))
            {
                AppLogger.Information($"Device {deviceId} already exists");
                return false;
            }

            var device = new MqttDeviceModel(deviceId, server, port, username, password, topicoptions, isConnected)
            {
                MqttClient = null
            };
            _devices[deviceId] = device;

            AppLogger.Information($"Device {deviceId} added successfully");
            return true;
        }
        catch (Exception ex)
        {
            AppLogger.Error(ex, $"Failed to add device {deviceId}: {ex.Message}");
            return false;
        }
    }

    /// <summary>
    /// 删除设备
    /// </summary>
    /// <param name="deviceId">设备Id</param>
    /// <returns></returns>
    public async Task<bool> RemoveDeviceAsync(string deviceId)
    {
        try
        {
            if (!_devices.TryGetValue(deviceId, out var device))
            {
                AppLogger.Warning($"Device {deviceId} not found");
                return false;
            }

            //根据设备字典中的DeviceId移除MqttDevice设备对象
            if (device.MqttClient.IsConnected)
            {
                AppLogger.Warning($"Device {deviceId} still connected, please disconnect first");
                return false;
            }

            AppLogger.Information($"Device {deviceId} removed successfully");
            return _devices.TryRemove(deviceId, out var devices);
        }
        catch (Exception e)
        {
            AppLogger.Error(e, $"Failed to remove device {deviceId}: {e.Message}");
            return false;
        }
    }

    /// <summary>
    /// 连接MQTT设备
    /// </summary>
    /// <param name="deviceId"></param>
    /// <returns></returns>
    public async Task<bool> ConnectDeviceAsync(string deviceId)
    {
        try
        {
            if (!_devices.TryGetValue(deviceId, out var device))
            {
                AppLogger.Warning($"DeviceFrom-(ConnectDeviceAsync) {deviceId} not found");
                return false;
            }

            if (device.MqttClient != null && device.MqttClient.IsConnected)
            {
                AppLogger.Information($"Device {deviceId} is already connected");
                return true;
            }

            var mqttClient = _mqttFactory.CreateMqttClient();
            device.MqttClient = mqttClient;
            // 配置连接选项
            var options = new MqttClientOptionsBuilder()
                .WithTcpServer(device.Server, device.Port)
                .WithCredentials(device.Username, device.Password)
                .Build();

            // 添加连接事件处理
            mqttClient.ConnectedAsync += async e =>
            {
                AppLogger.Information($"Device {deviceId} connected successfully");
                device.ConnectedTime = DateTime.Now;
                device.DeviceId = deviceId;
                device.IsConnected = true; // 更新设备连接状态为true
                DeviceStatusChanged?.Invoke(this, new DeviceStatusEventArgs(deviceId, true));
                // 连接成功后自动所有类型的主题
                foreach (var topicConfig in device.Topics)
                {
                    await SubscribeToTopicAsync(mqttClient, topicConfig.Topic,
                        (MqttQualityOfServiceLevel)topicConfig.Qos);
                }

                AppLogger.Information($"MessageFormat: {e.GetType().Name}: Device {deviceId} connected");
            };
            // 添加消息处理事件
            mqttClient.ApplicationMessageReceivedAsync += async e =>
            {
                var receivedTopic = e.ApplicationMessage.Topic;
                var payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
                AppLogger.Information($"MessageFormat: {e.GetType().Name}: Received message from device {deviceId}");
                HandleDeviceMessage(deviceId, receivedTopic, payload);
            };
            // 连接到MQTT代理
            await mqttClient.ConnectAsync(options, CancellationToken.None);

            return true;
        }
        catch (Exception e)
        {
            AppLogger.Information($"Failed to connect device {deviceId}: {e.Message}");
            throw;
        }
    }

    public async Task<bool> AddTopic(string deviceId, string topic, int qos = 0, bool isSubscription = true,
        bool isPublish = false)
    {
        try
        {
            if (!_devices.TryGetValue(deviceId, out var device))
            {
                AppLogger.Warning($"Device {deviceId} not found");
                return false;
            }

            var localTopicToRemove = device.Topics.FirstOrDefault(t => t.Topic == topic);
            if (localTopicToRemove != null)
            {
                // device.Topics.Add(localTopicToRemove);
                // 自动主题
                await SubscribeToTopicAsync(device.MqttClient, topic, (MqttQualityOfServiceLevel)qos);
            }

            return false;
        }
        catch (Exception e)
        {
            AppLogger.Error(e,
                $"Failed to subscribe topic {topic} for device {deviceId}: {e.Message} currentTime: {DateTime.Now}");
            return false;
        }
    }

    public async Task<bool> UnsubscribeTopic(string deviceId, string topic)
    {
        try
        {
            if (!_devices.TryGetValue(deviceId, out var device))
            {
                AppLogger.Warning($"Device {deviceId} not found");
                return false;
            }

            // 始终从本地主题列表中移除
            var localTopicToRemove = device.Topics.FirstOrDefault(t => t.Topic == topic);
            if (localTopicToRemove != null)
            {
                device.Topics.Remove(localTopicToRemove);
            }

            // 如果客户端已连接，也从服务器取消订阅
            if (device.MqttClient != null && device.MqttClient.IsConnected)
            {
                var unsubscribeResult = await device.MqttClient.UnsubscribeAsync(topic, CancellationToken.None);
                AppLogger.Information($"Unsubscribed from topic: {topic} for device: {deviceId}");
            }

            AppLogger.Information($"Unsubscribed from topic: {topic} currentTime: {DateTime.Now}");
            return true;
        }
        catch (OperationCanceledException)
        {
            AppLogger.Information($"Unsubscribe operation for device {deviceId} and topic {topic} was cancelled");
            return false;
        }
        catch (Exception e)
        {
            AppLogger.Error(e, $"Failed to unsubscribe topic {topic} for device {deviceId}: {e.Message}");
            return false;
        }
    }

    private async Task<bool> SubscribeToTopicAsync(IMqttClient mqttClient, string topic, MqttQualityOfServiceLevel qos)
    {
        try
        {
            AppLogger.Information($"Subscribing to topic: {topic}");

            await mqttClient.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
                .WithTopicFilter(topic, qos)
                .Build());

            AppLogger.Information($"Successfully subscribed to topic: {topic}");
            await mqttClient.PublishAsync(new MqttApplicationMessageBuilder()
                .WithTopic(topic)
                .WithPayload($"{{\"{topic}\": 订阅成功 }}")
                .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
                .Build());


            // 发送测试消息
            await mqttClient.PublishAsync(new MqttApplicationMessageBuilder()
                .WithTopic("modbus/test")
                .WithPayload("{\"register_0\": 30.2, \"register_1\": 41.5, \"register_10\":1,\"register_11\":9600}")
                .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
                .Build());

            AppLogger.Information("Sent self-test message after subscription");
            return true;
        }
        catch (Exception ex)
        {
            AppLogger.Error(ex, $"Failed to subscribe to topic {topic} - {ex.Message}");
            return false;
        }
    }

    /// <summary>
    /// 接收消息的处理方法
    /// </summary>
    /// <param name="deviceId"></param>
    /// <param name="topic"></param>
    /// <param name="payload"></param>
    private void HandleDeviceMessage(string deviceId, string topic, string payload)
    {
        try
        {
            // 解析消息 ，如果是Modbus消息，则使用ModbusData对象，其余类型使用MqttMessageDataModel对象
            var messageData = _messageParser.ParseMessage(deviceId, topic, payload);

            // 触发设备数据接收事件
            DeviceDataReceived?.Invoke(this, new DeviceDataEventArgs(
                deviceId, topic, payload, messageData));

            AppLogger.Information($"Processed message from device {deviceId} on topic {topic}");
        }
        catch (Exception ex)
        {
            AppLogger.Error(ex, $"Failed to process message from device {deviceId}: {ex.Message}");
        }
    }

    public async Task<bool> DisconnectDeviceAsync(string deviceId)
    {
        try
        {
            if (!_devices.TryGetValue(deviceId, out var device) || device.MqttClient == null)
            {
                AppLogger.Warning($"Device {deviceId} not found");
                return false;
            }

            if (device.MqttClient.IsConnected)
            {
                device.LastActivityTime = DateTime.Now;
                device.IsConnected = false;
                DeviceStatusChanged?.Invoke(this, new DeviceStatusEventArgs(deviceId, false));
                AppLogger.Warning($"Device {deviceId} is not connected");
                await device.MqttClient.DisconnectAsync(); // 断开连接 

                //device.MqttClient=null;  await device.MqttClient.DisconnectAsync(); 会自动释放掉MqttClient对象，不需要手动释放
                return true;
            }

            AppLogger.Warning($"Form(Disconnect-Message)Device {deviceId} is null");
            return false;
        }
        catch (Exception e)
        {
            AppLogger.Error(e, $"Failed to disconnect device {deviceId}: {e.Message}");
            return false;
        }
    }

    /// <summary>
    /// 获取设备
    /// </summary>
    /// <param name="deviceId">设备Id</param>
    /// <returns></returns>
    public MqttDeviceModel? GetDevice(string deviceId)
    {
        //先检查设备是否存在
        if (!_devices.ContainsKey(deviceId))
        {
            AppLogger.Warning($"Device From GetDevice{deviceId} not found");
            return null;
        }

        // 根据设备Id获取设备
        if (_devices.TryGetValue(deviceId, out var device))
        {
            return device;
        }

        AppLogger.Warning($"Device {deviceId} not found");
        return null;
    }

    /// <summary>
    /// 获取所有设备  
    /// </summary>
    /// <returns></returns>
    public IEnumerable<MqttDeviceModel> GetAllDevices()
    {
        return _devices.Values;
    }

    public bool ContainsDevice(string deviceId)
    {
        return _devices.ContainsKey(deviceId);
    }

    public bool IsDeviceConnected(string deviceId)
    {
        //为了应对Initialization的时候找不到设备
        if (!_devices.TryGetValue(deviceId, out var device) || device.MqttClient == null)
        {
            AppLogger.Warning($"Device From IsDeviceConnected-message: {deviceId} not found");
            return false;
        }


        return device.IsConnected;
    }

    public event EventHandler<DeviceStatusEventArgs>? DeviceStatusChanged;
    public event EventHandler<DeviceDataEventArgs>? DeviceDataReceived;
}